package com.common.utils;

import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;

/**
 * 线程任务重试工具类（通用逻辑，可复用）
 * <p>
 * 使用方式
 * ThreadTaskRetryUtil.executeWithRetry(tasks, (task)->{  执行任务  }, executor, retryTimes);
 */
@Slf4j
public class ThreadTaskRetryUtil {

    /**
     * 执行带重试的任务
     *
     * @param tasks         待执行的任务列表
     * @param taskProcessor 任务处理器（定义单条任务如何执行）
     * @param executor      线程池
     * @param retryTimes    最大重试次数
     * @return 最终失败的任务列表
     */
    public static <T> List<T> executeWithRetry(List<T> tasks, TaskProcessorConsumer<T> taskProcessor, Executor executor, int retryTimes) {

        List<T> finalFailedTasks = new CopyOnWriteArrayList<>();
        if (tasks.isEmpty() || retryTimes <= 0) {
            return finalFailedTasks;
        }

        log.info("开始执行重试的任务，共{}条，最大重试次数：{}", tasks.size(), retryTimes);
        CompletableFuture<?>[] futures = new CompletableFuture[tasks.size()];

        for (int i = 0; i < tasks.size(); i++) {
            final int taskIndex = i;
            T task = tasks.get(i);
            futures[i] = CompletableFuture.runAsync(() -> {
                boolean isSuccess = false;
                // 循环重试
                for (int attempt = 1; attempt <= retryTimes; attempt++) {
                    try {
                        log.info("失败任务[{}]第{}次执行", taskIndex, attempt);
                        taskProcessor.consumer(task); // 执行单条任务
                        isSuccess = true;
                        log.info("失败任务[{}]第{}次执行成功", taskIndex, attempt);
                        break; // 成功则退出重试
                    } catch (Exception e) {
                        log.error("失败任务[{}]第{}次执行失败", taskIndex, attempt, e);
                        if (attempt == retryTimes) {
                            log.error("失败任务[{}]达到最大重试次数({})，执行失败", taskIndex, retryTimes);
                        }
                    }
                }
                if (!isSuccess) {
                    finalFailedTasks.add(task); // 最终失败的任务
                }
            }, executor);
        }

        // 等待所有任务完成
        CompletableFuture.allOf(futures).join();
        log.info("重试任务执行完毕，原失败{}条，重试成功{}条，最终失败{}条", tasks.size(), tasks.size() - finalFailedTasks.size(), finalFailedTasks.size());
        return finalFailedTasks;
    }

    /**
     * 任务处理器接口（定义单条任务的执行逻辑）
     * 消费型接口
     */
    @FunctionalInterface
    public interface TaskProcessorConsumer<T> {
        void consumer(T task) throws Exception;
    }
}
